/*
 *Copyright 2021-2023 NERCIS
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
 */

package cn.ac.nercis.pes.service.document.report;

import cn.ac.nercis.pes.common.constant.common.BaseConstants;
import cn.ac.nercis.pes.common.constant.doc.ConclusionResult;
import cn.ac.nercis.pes.common.constant.evaluation.EvaluationConclusion;
import cn.ac.nercis.pes.common.constant.evaluation.OffsetConclusion;
import cn.ac.nercis.pes.common.constant.knowledge.LayerTarget;
import cn.ac.nercis.pes.common.constant.knowledge.TargetDeepness;
import cn.ac.nercis.pes.common.constant.project.SpecialType;
import cn.ac.nercis.pes.common.utils.ConvertUtils;
import cn.ac.nercis.pes.model.bo.doc.report.evaluation.AppendixOneBO;
import cn.ac.nercis.pes.model.bo.doc.report.table.EvaluationRecordTableBO;
import cn.ac.nercis.pes.model.bo.doc.report.table.record.MEvaluationRecordBO;
import cn.ac.nercis.pes.model.bo.doc.report.table.record.ResultRecordBO;
import cn.ac.nercis.pes.model.bo.doc.report.table.record.TEvaluationRecordBO;
import cn.ac.nercis.pes.repository.dal.evaluation.EvaluationRecordRepository;
import cn.ac.nercis.pes.repository.dal.evaluation.ResultCorrectionRepository;
import cn.ac.nercis.pes.repository.dal.project.SystemSpecialTargetRepository;
import cn.ac.nercis.pes.repository.dal.project.SystemTargetRepository;
import cn.ac.nercis.pes.repository.model.evaluation.EvaluationRecordDO;
import cn.ac.nercis.pes.repository.model.evaluation.ResultCorrectionDO;
import cn.ac.nercis.pes.repository.model.project.SystemDO;
import cn.ac.nercis.pes.repository.model.project.SystemSpecialTargetDO;
import cn.ac.nercis.pes.repository.model.project.SystemTargetDO;
import cn.ac.nercis.pes.service.utils.AssetUtils;
import cn.ac.nercis.pes.service.utils.CalculateUtils;
import cn.ac.nercis.pes.service.utils.FileManage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 密评报告测评记录数据服务类
 *
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
@Service
public record ReportRecordDataService(EvaluationRecordRepository evaluationRecordRepository,
                                      ResultCorrectionRepository resultCorrectionRepository,
                                      SystemTargetRepository systemTargetRepository,
                                      SystemSpecialTargetRepository systemSpecialTargetRepository) {
    private final static String OFFSET_SCORE_FORMAT = "%s*";

    @Autowired
    public ReportRecordDataService {
    }

    /**
     * 附录A，测评记录数据
     *
     * @return 返回附录A数据
     */
    public AppendixOneBO getEvaluationRecordData(SystemDO systemDO) {
        try {
            var systemTargets = this.systemTargetRepository.findAllBySystemId(systemDO.getId());
            var specialTargets = this.systemSpecialTargetRepository.findAllBySystemId(systemDO.getId());
            return AppendixOneBO.builder()
                    .pictureDir(FileManage.getPhotoFileBaseDir(systemDO.getId()))
                    .phyEnv(getPhyEnvRecord(systemDO, systemTargets, specialTargets))
                    .netCommunication(getNetCommunicationRecord(systemDO, systemTargets, specialTargets))
                    .deviceCompute(getDeviceComputeRecord(systemDO, systemTargets, specialTargets))
                    .appData(getAppDataRecord(systemDO, systemTargets, specialTargets))
                    .manageSystem(getManageSystemRecord(systemDO, systemTargets, specialTargets))
                    .personnelManage(getPersonnelManageRecord(systemDO, systemTargets, specialTargets))
                    .buildRunning(getBuildRunningRecord(systemDO, systemTargets, specialTargets))
                    .emergencyHandling(getEmergencyHandlingRecord(systemDO, systemTargets, specialTargets))
                    .build();
        } catch (RuntimeException rEx) {
            log.error("{}/getEvaluationRecordData 获取数据出错：{}", this.getClass().getName(), rEx.getMessage());
            throw rEx;
        }
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> getPhyEnvRecord(SystemDO systemDO,
                                                                         List<SystemTargetDO> systemTargets,
                                                                         List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.PHY_ENV, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return phyEnvByEmpty();
        }
        var evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId())
                .stream()
                .sorted(Comparator.comparing((er) -> Objects.nonNull(er.getAsset().getQuoteAssetId()) ? er.getAsset().getQuoteAssetId() : er.getAsset().getClassId()))
                .toList();
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.1");
        data.setContent(getTEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget, resultCorrections));
        return data;
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> getNetCommunicationRecord(SystemDO systemDO, List<SystemTargetDO> systemTargets,
                                                                                   List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.NET_COMMUNICATION, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return netCommunicationByEmpty();
        }
        List<EvaluationRecordDO> evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId());
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.2");
        data.setContent(getTEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget, resultCorrections));
        return data;
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> getDeviceComputeRecord(SystemDO systemDO, List<SystemTargetDO> systemTargets,
                                                                                List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.DEVICE_COMPUTE, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return deviceComputeByEmpty();
        }
        List<EvaluationRecordDO> evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId());
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.3");
        data.setContent(getTEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget,resultCorrections));
        return data;
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> getAppDataRecord(SystemDO systemDO, List<SystemTargetDO> systemTargets,
                                                                          List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.APP_DATA, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return appDataByEmpty();
        }
        List<EvaluationRecordDO> evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId())
                .stream()
                .sorted(Comparator.comparing((er) -> Objects.nonNull(er.getAsset().getQuoteAssetId()) ? er.getAsset().getQuoteAssetId() : er.getAsset().getClassId()))
                .toList();
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.4");
        data.setContent(getTEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget, resultCorrections));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> getManageSystemRecord(SystemDO systemDO, List<SystemTargetDO> systemTargets,
                                                                               List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.MANAGE_SYSTEM, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return manageSystemByEmpty();
        }
        List<EvaluationRecordDO> evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId());
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.5");
        data.setContent(getMEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget, resultCorrections));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> getPersonnelManageRecord(SystemDO systemDO, List<SystemTargetDO> systemTargets,
                                                                                  List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.PERSONNEL_MANAGE, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return personnelManageByEmpty();
        }
        List<EvaluationRecordDO> evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId());
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.6");
        data.setContent(getMEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget, resultCorrections));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> getBuildRunningRecord(SystemDO systemDO, List<SystemTargetDO> systemTargets,
                                                                               List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.BUILD_RUNNING, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return buildRunningByEmpty();
        }
        List<EvaluationRecordDO> evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId());
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.7");
        data.setContent(getMEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget, resultCorrections));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> getEmergencyHandlingRecord(SystemDO systemDO, List<SystemTargetDO> systemTargets,
                                                                                    List<SystemSpecialTargetDO> specialTargets) {
        SystemTargetDO layerTarget = getLayerTargetByName(LayerTarget.EMERGENCY_HANDLING, systemTargets);
        if (Objects.isNull(layerTarget)) {
            return emergencyHandlingByEmpty();
        }
        List<EvaluationRecordDO> evaluationRecords = evaluationRecordRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(), layerTarget.getKmTargetId());
        var resultCorrections = resultCorrectionRepository.findAllBySystemIdAndLayerTargetId(systemDO.getId(),layerTarget.getKmTargetId());
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.8");
        data.setContent(getMEvalRecordContent(evaluationRecords, systemTargets, specialTargets, layerTarget, resultCorrections));
        return data;
    }

    private List<TEvaluationRecordBO> getTEvalRecordContent(List<EvaluationRecordDO> evaluationRecords,
                                                            List<SystemTargetDO> systemTargets,
                                                            List<SystemSpecialTargetDO> specialTargets,
                                                            SystemTargetDO layerTarget,
                                                            List<ResultCorrectionDO> resultCorrections) {
        var standContent = systemTargets.stream()
                .filter(st -> StringUtils.equals(st.getKmParentId(), layerTarget.getKmTargetId()))
                .sorted(Comparator.comparingInt(SystemTargetDO::getKmSort))
                .flatMap(ut -> toTEvaluationRecordBO(ut, evaluationRecords,resultCorrections).stream())
                .collect(Collectors.toList());
        var specialContent = specialTargets.stream()
                .filter(st-> StringUtils.equals(st.getLayerTargetId(), layerTarget.getKmTargetId())
                        && (st.getSpecialType()== SpecialType.UPLEVEL || st.getSpecialType()==SpecialType.CUSTOM))
                .sorted(Comparator.comparingInt(SystemSpecialTargetDO::getSort))
                .flatMap(ut -> toTEvaluationRecordBO(ut, evaluationRecords).stream())
                .toList();
        if (CollectionUtils.isEmpty(standContent) && CollectionUtils.isEmpty(specialContent)) {
            standContent.add(tEvaluationRecordByEmpty());
        }
        return Stream.concat(standContent.stream(),specialContent.stream()).toList();
    }

    private List<MEvaluationRecordBO> getMEvalRecordContent(List<EvaluationRecordDO> evaluationRecords, List<SystemTargetDO> systemTargets,
                                                            List<SystemSpecialTargetDO> specialTargets,
                                                            SystemTargetDO layerTarget,
                                                            List<ResultCorrectionDO> resultCorrections) {

        var standContent = systemTargets.stream()
                .filter(st -> StringUtils.equals(st.getKmParentId(), layerTarget.getKmTargetId()))
                .sorted(Comparator.comparingInt(SystemTargetDO::getKmSort))
                .flatMap(ut -> toMEvaluationRecordBO(ut, evaluationRecords, resultCorrections).stream())
                .collect(Collectors.toList());
        var specialContent = specialTargets.stream()
                .filter(st-> StringUtils.equals(st.getLayerTargetId(), layerTarget.getKmTargetId())
                        && (st.getSpecialType()== SpecialType.UPLEVEL || st.getSpecialType()==SpecialType.CUSTOM))
                .sorted(Comparator.comparingInt(SystemSpecialTargetDO::getSort))
                .flatMap(ut -> toMEvaluationRecordBO(ut, evaluationRecords).stream())
                .toList();
        if (CollectionUtils.isEmpty(standContent) && CollectionUtils.isEmpty(specialContent)) {
            standContent.add(mEvaluationRecordByEmpty());
        }
        return Stream.concat(standContent.stream(),specialContent.stream()).toList();
    }

    private List<TEvaluationRecordBO> toTEvaluationRecordBO(SystemTargetDO unitTarget, List<EvaluationRecordDO> evaluationRecords,
                                                            List<ResultCorrectionDO> resultCorrections) {
        var unitRecords = evaluationRecords.stream()
                .filter(er -> StringUtils.equals(er.getUnitTargetId(), unitTarget.getKmTargetId()))
                .collect(Collectors.toList());
        var unitResultCorrections = resultCorrections.stream()
                .filter(rc-> rc.getResult() != OffsetConclusion.DEFAULT
                        && StringUtils.equals(rc.getUnitTargetId(),unitTarget.getKmTargetId()))
                .toList();
        if (CollectionUtils.isEmpty(unitRecords)) {
            return Collections.singletonList(TEvaluationRecordBO.builder()
                    .target(unitTarget.getKmName())
                    .asset("")
                    .isApplyByAsset(false)
                    .isApply(unitTarget.getIsApply())
                    .records(Collections.singletonList(ResultRecordBO.builder()
                            .content(StringUtils.isEmpty(unitTarget.getReasons()) ? " " : unitTarget.getReasons())
                            .pictures(new ArrayList<>())
                            .build()))
                    .dValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                    .aValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                    .kValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                    .assetScore(ConvertUtils.scoreToString(null))
                    .unitScore(ConvertUtils.scoreToString(null))
                    .build());
        }
        EvaluationConclusion unitConclusion = CalculateUtils.getUnitEvalConclusion(unitRecords);
        var unitScore = ConvertUtils.scoreToString(unitConclusion == EvaluationConclusion.NOT_APPLICABLE ? null : CalculateUtils.getUnitScore(unitRecords));
        var offsetUnitScore = ConvertUtils.scoreToString(unitConclusion == EvaluationConclusion.NOT_APPLICABLE ? null : CalculateUtils.getUnitScore(unitRecords,unitResultCorrections), StringUtils.EMPTY);
        return unitRecords.stream()
                .map(er -> {
                    List<ResultRecordBO> resultRecords = new ArrayList<>();
                    if (er.getConclusion() == EvaluationConclusion.NOT_APPLICABLE) {
                        String content = Stream.of(er.getContent(), er.getDContent())
                                .filter(StringUtils::isNotBlank)
                                .findFirst()
                                .orElse(" ");
                        List<String> pictures = new ArrayList<>();
                        if (StringUtils.isNotBlank(er.getDFiles()) || StringUtils.isNotBlank(er.getManageFiles())) {
                            Stream.of(er.getDFiles(), er.getManageFiles())
                                    .filter(StringUtils::isNotBlank)
                                    .flatMap(fileNames -> Arrays.stream(StringUtils.split(fileNames, BaseConstants.MULTI_SPLIT_CHAR)))
                                    .filter(StringUtils::isNotBlank)
                                    .forEach(pictures::add);
                        }
                        resultRecords.add(ResultRecordBO.builder()
                                .content(content)
                                .pictures(pictures)
                                .build());
                    } else {
                        Stream.of(toDResultRecordDTO(er), toAResultRecordDTO(er), toKResultRecordDTO(er))
                                .filter(Objects::nonNull)
                                .forEach(resultRecords::add);
                    }
                    if (CollectionUtils.isEmpty(resultRecords)) {
                        resultRecords.add(resultRecordByEmpty());
                    }
                    var offsetAssetScore = resultCorrections.stream()
                            .filter(r->StringUtils.equals(r.getRecord().getId(),er.getId()))
                            .map(rc->{
                                var score = ConvertUtils.scoreToString(rc.getScore(), StringUtils.EMPTY);
                                return StringUtils.isNotBlank(score) ? String.format(OFFSET_SCORE_FORMAT,score) : score;
                            })
                            .findFirst()
                            .orElse(null);
                    return TEvaluationRecordBO.builder()
                            .target(unitTarget.getKmName())
                            .asset(AssetUtils.getAssetName(er.getAsset()))
                            .isApplyByAsset(er.getConclusion() != EvaluationConclusion.NOT_APPLICABLE)
                            .isApply(unitTarget.getIsApply())
                            .records(resultRecords)
                            .dValue(er.getDResult().getResult())
                            .aValue(er.getAResult().getResult())
                            .kValue(er.getKResult().getResult())
                            .assetScore(ConvertUtils.scoreToString(er.getScore()))
                            .offsetAssetScore(offsetAssetScore)
                            .unitScore(unitScore)
                            .offsetUnitScore(getOffsetUnitScore(offsetUnitScore, unitScore))
                            .build();
                })
                .toList();
    }

    private List<TEvaluationRecordBO> toTEvaluationRecordBO(SystemSpecialTargetDO unitTarget,
                                                            List<EvaluationRecordDO> evaluationRecords) {
        var unitRecords = evaluationRecords.stream()
                .filter(er -> StringUtils.equals(er.getUnitTargetId(), unitTarget.getId()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(unitRecords)) {
            return Collections.singletonList(TEvaluationRecordBO.builder()
                    .target(unitTarget.getName())
                    .asset("")
                    .isApplyByAsset(false)
                    .isApply(true)
                    .records(Collections.singletonList(ResultRecordBO.builder()
                            .content(StringUtils.isEmpty(unitTarget.getReasons()) ? " " : unitTarget.getReasons())
                            .pictures(new ArrayList<>())
                            .build()))
                    .dValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                    .aValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                    .kValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                    .assetScore(ConvertUtils.scoreToString(null))
                    .unitScore(ConvertUtils.scoreToString(null))
                    .build());
        }
        EvaluationConclusion unitConclusion = CalculateUtils.getUnitEvalConclusion(unitRecords);
        var unitScore = ConvertUtils.scoreToString(unitConclusion == EvaluationConclusion.NOT_APPLICABLE ? null : CalculateUtils.getUnitScore(unitRecords));
        return unitRecords.stream()
                .map(er -> {
                    List<ResultRecordBO> resultRecords = new ArrayList<>();
                    if (er.getConclusion() == EvaluationConclusion.NOT_APPLICABLE) {
                        String content = Stream.of(er.getContent(), er.getDContent())
                                .filter(StringUtils::isNotBlank)
                                .findFirst()
                                .orElse(" ");
                        List<String> pictures = new ArrayList<>();
                        if (StringUtils.isNotBlank(er.getDFiles()) || StringUtils.isNotBlank(er.getManageFiles())) {
                            Stream.of(er.getDFiles(), er.getManageFiles())
                                    .filter(StringUtils::isNotBlank)
                                    .flatMap(fileNames -> Arrays.stream(StringUtils.split(fileNames, BaseConstants.MULTI_SPLIT_CHAR)))
                                    .filter(StringUtils::isNotBlank)
                                    .forEach(pictures::add);
                        }
                        resultRecords.add(ResultRecordBO.builder()
                                .content(content)
                                .pictures(pictures)
                                .build());
                    } else {
                        Stream.of(toDResultRecordDTO(er), toAResultRecordDTO(er), toKResultRecordDTO(er))
                                .filter(Objects::nonNull)
                                .forEach(resultRecords::add);
                    }
                    if (CollectionUtils.isEmpty(resultRecords)) {
                        resultRecords.add(resultRecordByEmpty());
                    }
                    return TEvaluationRecordBO.builder()
                            .target(unitTarget.getName())
                            .asset(AssetUtils.getAssetName(er.getAsset()))
                            .isApplyByAsset(er.getConclusion() != EvaluationConclusion.NOT_APPLICABLE)
                            .isApply(true)
                            .records(resultRecords)
                            .dValue(er.getDResult().getResult())
                            .aValue(er.getAResult().getResult())
                            .kValue(er.getKResult().getResult())
                            .assetScore(ConvertUtils.scoreToString(er.getScore()))
                            .unitScore(unitScore)
                            .build();
                })
                .toList();
    }

    private List<MEvaluationRecordBO> toMEvaluationRecordBO(SystemTargetDO unitTarget, List<EvaluationRecordDO> evaluationRecords,
                                                            List<ResultCorrectionDO> resultCorrections) {
        List<EvaluationRecordDO> unitRecords = evaluationRecords.stream()
                .filter(er -> StringUtils.equals(er.getUnitTargetId(), unitTarget.getKmTargetId()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(unitRecords)) {
            return Collections.singletonList(MEvaluationRecordBO.builder()
                    .target(unitTarget.getKmName())
                    .asset("")
                    .isApplyByAsset(false)
                    .isApply(unitTarget.getIsApply())
                    .records(Collections.singletonList(ResultRecordBO.builder()
                            .content(StringUtils.isEmpty(unitTarget.getReasons()) ? " " : unitTarget.getReasons())
                            .pictures(new ArrayList<>())
                            .build()))
                    .result(EvaluationConclusion.NOT_APPLICABLE.getName())
                    .unitScore(ConvertUtils.scoreToString(null))
                    .build());
        }
        var unitResultCorrections = resultCorrections.stream()
                .filter(rc-> rc.getResult() != OffsetConclusion.DEFAULT
                        && StringUtils.equals(rc.getUnitTargetId(),unitTarget.getKmTargetId()))
                .toList();
        EvaluationConclusion unitConclusion = CalculateUtils.getUnitEvalConclusion(unitRecords);
        String unitScore = ConvertUtils.scoreToString(unitConclusion == EvaluationConclusion.NOT_APPLICABLE ? null : CalculateUtils.getUnitScore(unitRecords));
        var offsetUnitScore = ConvertUtils.scoreToString(unitConclusion == EvaluationConclusion.NOT_APPLICABLE ? null : CalculateUtils.getUnitScore(unitRecords,unitResultCorrections), StringUtils.EMPTY);
        return unitRecords.stream()
                .map(er -> {
                    List<ResultRecordBO> resultRecords = new ArrayList<>();
                    if (er.getConclusion() == EvaluationConclusion.NOT_APPLICABLE) {
                        resultRecords.add(ResultRecordBO.builder()
                                .content(StringUtils.isEmpty(er.getContent()) ? " " : er.getContent())
                                .pictures(new ArrayList<>())
                                .build());
                    } else {
                        ResultRecordBO result = toManageResultRecordDTO(er);
                        if (Objects.nonNull(result)) {
                            resultRecords.add(result);
                        }
                    }
                    if (CollectionUtils.isEmpty(resultRecords)) {
                        resultRecords.add(resultRecordByEmpty());
                    }
                    return MEvaluationRecordBO.builder()
                            .target(unitTarget.getKmName())
                            .asset(AssetUtils.getAssetName(er.getAsset()))
                            .isApplyByAsset(er.getConclusion() != EvaluationConclusion.NOT_APPLICABLE)
                            .isApply(unitTarget.getIsApply())
                            .records(resultRecords)
                            .result(er.getConclusion().getName())
                            .unitScore(unitScore)
                            .offsetUnitScore(getOffsetUnitScore(offsetUnitScore, unitScore))
                            .build();
                })
                .toList();
    }

    private List<MEvaluationRecordBO> toMEvaluationRecordBO(SystemSpecialTargetDO unitTarget, List<EvaluationRecordDO> evaluationRecords) {
        List<EvaluationRecordDO> unitRecords = evaluationRecords.stream()
                .filter(er -> StringUtils.equals(er.getUnitTargetId(), unitTarget.getId()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(unitRecords)) {
            return Collections.singletonList(MEvaluationRecordBO.builder()
                    .target(unitTarget.getName())
                    .asset("")
                    .isApplyByAsset(false)
                    .isApply(true)
                    .records(Collections.singletonList(ResultRecordBO.builder()
                            .content(StringUtils.isEmpty(unitTarget.getReasons()) ? " " : unitTarget.getReasons())
                            .pictures(new ArrayList<>())
                            .build()))
                    .result(EvaluationConclusion.NOT_APPLICABLE.getName())
                    .unitScore(ConvertUtils.scoreToString(null))
                    .build());
        }
        EvaluationConclusion unitConclusion = CalculateUtils.getUnitEvalConclusion(unitRecords);
        String unitScore = ConvertUtils.scoreToString(unitConclusion == EvaluationConclusion.NOT_APPLICABLE ? null : CalculateUtils.getUnitScore(unitRecords));
        return unitRecords.stream()
                .map(er -> {
                    List<ResultRecordBO> resultRecords = new ArrayList<>();
                    if (er.getConclusion() == EvaluationConclusion.NOT_APPLICABLE) {
                        resultRecords.add(ResultRecordBO.builder()
                                .content(StringUtils.isEmpty(er.getContent()) ? " " : er.getContent())
                                .pictures(new ArrayList<>())
                                .build());
                    } else {
                        ResultRecordBO result = toManageResultRecordDTO(er);
                        if (Objects.nonNull(result)) {
                            resultRecords.add(result);
                        }
                    }
                    if (CollectionUtils.isEmpty(resultRecords)) {
                        resultRecords.add(resultRecordByEmpty());
                    }
                    return MEvaluationRecordBO.builder()
                            .target(unitTarget.getName())
                            .asset(AssetUtils.getAssetName(er.getAsset()))
                            .isApplyByAsset(er.getConclusion() != EvaluationConclusion.NOT_APPLICABLE)
                            .isApply(true)
                            .records(resultRecords)
                            .result(er.getConclusion().getName())
                            .unitScore(unitScore)
                            .build();
                })
                .collect(Collectors.toList());
    }

    private String getOffsetUnitScore(String offsetUnitScore,String unitScore){
        if(StringUtils.isBlank(offsetUnitScore) || StringUtils.equals(offsetUnitScore,unitScore)){
            return StringUtils.EMPTY;
        }
        return String.format(OFFSET_SCORE_FORMAT,offsetUnitScore);
    }

    private ResultRecordBO toDResultRecordDTO(EvaluationRecordDO recordDO) {
        if (StringUtils.isBlank(recordDO.getDContent()) && StringUtils.isBlank(recordDO.getDFiles())) {
            return null;
        }
        List<String> pictures = new ArrayList<>();
        if (StringUtils.isNotBlank(recordDO.getDFiles())) {
            Stream.of(StringUtils.split(recordDO.getDFiles(), BaseConstants.MULTI_SPLIT_CHAR))
                    .filter(StringUtils::isNotBlank)
                    .forEach(pictures::add);
        }
        return ResultRecordBO.builder()
                .content(StringUtils.isBlank(recordDO.getDContent()) ? " " : recordDO.getDContent())
                .pictures(pictures)
                .build();
    }

    private ResultRecordBO toAResultRecordDTO(EvaluationRecordDO recordDO) {
        if (StringUtils.isBlank(recordDO.getAContent()) && StringUtils.isBlank(recordDO.getAFiles())) {
            return null;
        }
        List<String> pictures = new ArrayList<>();
        if (StringUtils.isNotBlank(recordDO.getAFiles())) {
            Stream.of(StringUtils.split(recordDO.getAFiles(), BaseConstants.MULTI_SPLIT_CHAR))
                    .filter(StringUtils::isNotBlank)
                    .forEach(pictures::add);
        }
        return ResultRecordBO.builder()
                .content(StringUtils.isBlank(recordDO.getAContent()) ? " " : recordDO.getAContent())
                .pictures(pictures)
                .build();
    }

    private ResultRecordBO toKResultRecordDTO(EvaluationRecordDO recordDO) {
        if (StringUtils.isBlank(recordDO.getKContent()) && StringUtils.isBlank(recordDO.getKFiles())) {
            return null;
        }
        List<String> pictures = new ArrayList<>();
        if (StringUtils.isNotBlank(recordDO.getKFiles())) {
            Stream.of(StringUtils.split(recordDO.getKFiles(), BaseConstants.MULTI_SPLIT_CHAR))
                    .filter(StringUtils::isNotBlank)
                    .forEach(pictures::add);
        }
        return ResultRecordBO.builder()
                .content(StringUtils.isBlank(recordDO.getKContent()) ? " " : recordDO.getKContent())
                .pictures(pictures)
                .build();
    }

    private ResultRecordBO toManageResultRecordDTO(EvaluationRecordDO recordDO) {
        if (StringUtils.isBlank(recordDO.getContent()) && StringUtils.isBlank(recordDO.getManageFiles())) {
            return null;
        }
        List<String> pictures = new ArrayList<>();
        if (StringUtils.isNotBlank(recordDO.getManageFiles())) {
            Stream.of(StringUtils.split(recordDO.getManageFiles(), BaseConstants.MULTI_SPLIT_CHAR))
                    .filter(StringUtils::isNotBlank)
                    .forEach(pictures::add);
        }
        return ResultRecordBO.builder()
                .content(StringUtils.isBlank(recordDO.getContent()) ? " " : recordDO.getContent())
                .pictures(pictures)
                .build();
    }

    private SystemTargetDO getLayerTargetByName(LayerTarget target, List<SystemTargetDO> systemTargets) {
        return systemTargets.stream()
                .filter(st -> st.getKmDeepness() == TargetDeepness.LAYER.getDeepness()
                        && StringUtils.equals(target.getName(), st.getKmName()))
                .findFirst()
                .orElse(null);
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> phyEnvByEmpty() {
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.1");
        data.setContent(Collections.singletonList(tEvaluationRecordByEmpty()));
        return data;
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> netCommunicationByEmpty() {
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.2");
        data.setContent(Collections.singletonList(tEvaluationRecordByEmpty()));
        return data;
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> deviceComputeByEmpty() {
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.3");
        data.setContent(Collections.singletonList(tEvaluationRecordByEmpty()));
        return data;
    }

    private EvaluationRecordTableBO<TEvaluationRecordBO> appDataByEmpty() {
        EvaluationRecordTableBO<TEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.4");
        data.setContent(Collections.singletonList(tEvaluationRecordByEmpty()));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> manageSystemByEmpty() {
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.5");
        data.setContent(Collections.singletonList(mEvaluationRecordByEmpty()));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> personnelManageByEmpty() {
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.6");
        data.setContent(Collections.singletonList(mEvaluationRecordByEmpty()));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> buildRunningByEmpty() {
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.7");
        data.setContent(Collections.singletonList(mEvaluationRecordByEmpty()));
        return data;
    }

    private EvaluationRecordTableBO<MEvaluationRecordBO> emergencyHandlingByEmpty() {
        EvaluationRecordTableBO<MEvaluationRecordBO> data = new EvaluationRecordTableBO<>();
        data.setItemSymbol("A.8");
        data.setContent(Collections.singletonList(mEvaluationRecordByEmpty()));
        return data;
    }

    private TEvaluationRecordBO tEvaluationRecordByEmpty() {
        return TEvaluationRecordBO.builder()
                .target(" ")
                .asset(" ")
                .isApplyByAsset(true)
                .isApply(true)
                .records(Collections.singletonList(resultRecordByEmpty()))
                .dValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                .aValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                .kValue(ConclusionResult.NOT_APPLICABLE.getConclusion())
                .assetScore("0").unitScore("0")
                .build();
    }

    private MEvaluationRecordBO mEvaluationRecordByEmpty() {
        return MEvaluationRecordBO.builder()
                .target(" ")
                .asset(" ")
                .isApplyByAsset(true)
                .isApply(true)
                .records(Collections.singletonList(resultRecordByEmpty()))
                .result("符合").unitScore("1")
                .build();
    }

    private ResultRecordBO resultRecordByEmpty() {
        return ResultRecordBO.builder()
                .content(" ")
                .pictures(new ArrayList<>())
                .build();
    }
}
